package com.htstar.ovms.enterprise.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.htstar.ovms.admin.api.entity.EtpInfo;
import com.htstar.ovms.admin.api.feign.EtpInfoFeign;
import com.htstar.ovms.admin.api.vo.EtpInfoSVo;
import com.htstar.ovms.common.core.util.R;
import com.htstar.ovms.common.security.service.OvmsUser;
import com.htstar.ovms.common.security.util.SecurityUtils;
import com.htstar.ovms.device.api.entity.DeviceLastData;
import com.htstar.ovms.device.api.feign.DeviceAlarmFeign;
import com.htstar.ovms.enterprise.api.constant.TimeTypeConstant;
import com.htstar.ovms.enterprise.api.vo.AlarmDataVo;
import com.htstar.ovms.enterprise.api.vo.ApplyCarDataVo;
import com.htstar.ovms.enterprise.api.vo.CarDataVo;
import com.htstar.ovms.enterprise.service.*;
import lombok.extern.slf4j.Slf4j;
import org.omg.PortableInterceptor.INACTIVE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.hutool.core.util.NumberUtil.roundStr;

/**
 * Description:
 * Author: lw
 * Date: Created in 2020/7/16
 * Company: 航通星空
 * Modified By:
 *
 * @author liuwei
 */
@Service
@Slf4j
public class CarDataAnalysisServiceImpl implements CarDataAnalysisService {
    @Autowired
    private CarInfoService carInfoService;
    @Autowired
    private CarDeviceService carDeviceService;
    @Autowired
    private CarInsItemService carInsItemService;
    @Autowired
    private ApplyCarOrderService carOrderService;
    @Autowired
    private DeviceAlarmFeign alarmFeign;
    @Autowired
    private CarMaiItemService carMaiItemService;
    @Autowired
    private CarMotItemService carMotItemService;

    @Autowired
    private EtpInfoFeign etpInfoFeign;


    /**
     * 获取企业车辆数据概要
     *
     * @return
     */
    @Override
    public CarDataVo getCarDataByEtp(EtpInfo etpInfo) {
        OvmsUser user = SecurityUtils.getUser();
        Integer etpId = user.getEtpId();
        if (etpInfo.getId() != null) {
            etpId = etpInfo.getId();
        }
        //车辆数据
        CarDataVo carDataVo = new CarDataVo();
        //企业车辆数据 --已添加车辆数
        Integer carCount = carInfoService.getCarCount(etpId);
        //企业已绑定设备数量
        Integer deviceSnCount = carDeviceService.getDeviceSnByEtp(etpId);

        //设备在线数
        Integer online = carDeviceService.getOnline(etpId);
        LocalDate localDate = LocalDate.now();
        //保险过期
        Integer InsCount = carInsItemService.expiredNumByEtp(etpId, localDate);
        //保养过期
        Integer maiCount = carMaiItemService.expiredNumByEtp(etpId, localDate);
        //年检过期
        Integer motCount = carMotItemService.expiredNumByEtp(etpId, localDate);
        carDataVo.setCarCount(carCount);
        carDataVo.setDeviceSn(deviceSnCount);
        carDataVo.setInsurance(InsCount);
        carDataVo.setMaintenance(maiCount);
        carDataVo.setMot(motCount);
        carDataVo.setOnline(online);
        carDataVo.setNotOnline(deviceSnCount - online);
        carDataVo.setNoDeviceSn(carCount - deviceSnCount);
        return carDataVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CarDataVo getCarDataByMultiEtp(EtpInfo etpInfo) {
        OvmsUser user = SecurityUtils.getUser();
        Integer etpId = user.getEtpId();
        if (etpInfo.getId() != null) {
            etpId = etpInfo.getId();
        }
        //获取该企业下的后代企业ids
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(etpId);
        EtpInfoSVo etpInfoSVo = currentAndParents1.get(0);
        List<Integer> ids = etpInfoSVo.getIds();

//        List<Integer> ids = carDeviceService.getDescendantForEtpId(etpId);
        ids.add(etpId);
        etpInfo.setEtpIds(ids);
        List<Integer> collect = ids.stream().distinct().collect(Collectors.toList());
        CarDataVo carDataVo = new CarDataVo();
        //获取该企业下所有车辆
//      Integer allCarCount =  carInfoService.getAllCarCount(ids);

        ArrayList<Integer> carCountVOList = new ArrayList<>();
        int carCountVO = 0;

        ArrayList<Integer> deviceSnCountVOList = new ArrayList<>();
        int deviceSnCountVO = 0;

        ArrayList<Integer> InsCountVOList = new ArrayList<>();
        int InsCountVO = 0;

        ArrayList<Integer> maiCountVOList = new ArrayList<>();
        int maiCountVO = 0;

        ArrayList<Integer> motCountVOList = new ArrayList<>();
        int motCountVO = 0;

        ArrayList<Integer> onlineVOList = new ArrayList<>();
        int onlineVO = 0;

        for (Integer id : collect) {
            //车辆数据
            //企业车辆数据 --已添加车辆数
            Integer carCount = carInfoService.getCarCount(id);
            carCountVOList.add(carCount);
            //企业已绑定设备数量
            Integer deviceSnCount = carDeviceService.getDeviceSnByEtp(id);
            deviceSnCountVOList.add(deviceSnCount);

            //设备在线数
            Integer online = carDeviceService.getOnline(id);
            onlineVOList.add(online);

            LocalDate localDate = LocalDate.now();
            //保险过期
            Integer InsCount = carInsItemService.expiredNumByEtp(id, localDate);
            InsCountVOList.add(InsCount);
            //保养过期
            Integer maiCount = carMaiItemService.expiredNumByEtp(id, localDate);
            maiCountVOList.add(maiCount);
            //年检过期
            Integer motCount = carMotItemService.expiredNumByEtp(id, localDate);
            motCountVOList.add(motCount);
        }
        //
        for (Integer integer : carCountVOList) {
            carCountVO += integer;
        }
        carDataVo.setCarCount(carCountVO);
        //
        for (Integer integer : deviceSnCountVOList) {
            deviceSnCountVO += integer;
        }
        carDataVo.setDeviceSn(deviceSnCountVO);
        //
        for (Integer integer : InsCountVOList) {
            InsCountVO += integer;
        }
        carDataVo.setInsurance(InsCountVO);
        //
        for (Integer integer : maiCountVOList) {
            maiCountVO += integer;
        }
        carDataVo.setMaintenance(maiCountVO);
        //
        for (Integer integer : motCountVOList) {
            motCountVO += integer;
        }
        carDataVo.setMot(motCountVO);
        //
        for (Integer integer : onlineVOList) {
            onlineVO += integer;
        }
        carDataVo.setOnline(onlineVO);
        carDataVo.setNotOnline(deviceSnCountVO - onlineVO);
        carDataVo.setNoDeviceSn(carCountVO - deviceSnCountVO);

        List<DeviceLastData> carStatus = carDeviceService.getCarStatus(etpInfo);
        int allStop = 0;
        int allOnine = 0;
        int pullOut = 0;
        int allErr = 0;
        for (DeviceLastData record : carStatus) {
            if (record.getPull().equals(0) && record.getOnline().equals(0)) {
                allStop++;
            }
            if (record.getPull().equals(0) && record.getOnline().equals(1)) {
                allOnine++;
            }
            boolean a = record.getPull().equals(1) && record.getOnline().equals(0);//pull==1&&online==0
            boolean b = record.getPull().equals(1) && record.getOnline().equals(3);//pull==1&&online==3
            if (a || b) {
//                record.setOnline(2); //这两种状态online==2
                pullOut++;
            }
            if (record.getPull().equals(0) && record.getOnline().equals(3)) {
                allErr++;
            }
        }
        int noActive = 0;
        noActive = carDataVo.getCarCount() == null ? 0 : carDataVo.getCarCount() - allStop - allOnine - pullOut - allErr;
        carDataVo.setAllStop(allStop);
        carDataVo.setAllOnline(allOnine);
        carDataVo.setPullOut(pullOut);
        carDataVo.setAllErr(allErr);
        carDataVo.setNoActive(noActive);
        return carDataVo;
    }

    /**
     * 用车数据
     *
     * @param timeType
     * @return
     */
    @Override
    public ApplyCarDataVo getApplyCarData(Integer timeType, EtpInfo etpInfo) {
        OvmsUser user = SecurityUtils.getUser();
        Integer etpId = user.getEtpId();
        if (etpInfo.getId() != null) {
            etpId = etpInfo.getId();
        }
        Date date = this.getDate(timeType);
        ApplyCarDataVo applyCarDataVo = carOrderService.applyCarData(date, etpId);
        return applyCarDataVo;
    }

    @Override
    public ApplyCarDataVo getApplyCarDataByMultiEtp(Integer timeType, EtpInfo etpInfo) {
        OvmsUser user = SecurityUtils.getUser();
        Integer etpId = user.getEtpId();
        if (etpInfo.getId() != null) {
            etpId = etpInfo.getId();
        }
        Date date = this.getDate(timeType);
        //获取该企业下的后代企业ids
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(etpId);
        EtpInfoSVo etpInfoSVo = currentAndParents1.get(0);
        List<Integer> ids = etpInfoSVo.getIds();
        ids.add(etpId);
        List<Integer> collect = ids.stream().distinct().collect(Collectors.toList());

        ArrayList<ApplyCarDataVo> ApplyCarDataVoList = new ArrayList<>();
        for (Integer id : collect) {
            ApplyCarDataVo applyCarDataVo = carOrderService.applyCarData(date, id);
            Integer carCount1 = carInfoService.getCarCount1(id);
            applyCarDataVo.setAllCarCount(carCount1);
            ApplyCarDataVoList.add(applyCarDataVo);
        }
        ApplyCarDataVo applyCarDataVo = new ApplyCarDataVo();
        applyCarDataVo.setSumCount(0);
        applyCarDataVo.setInuseCount(0);
        applyCarDataVo.setAllCarCount(0);
        for (ApplyCarDataVo item : ApplyCarDataVoList) {
            applyCarDataVo.setSumCount(applyCarDataVo.getSumCount() + item.getSumCount());//总用车数
            applyCarDataVo.setInuseCount(applyCarDataVo.getInuseCount() + item.getInuseCount());//总在用数
            applyCarDataVo.setAllCarCount(applyCarDataVo.getAllCarCount() + item.getAllCarCount());//总拥有车数
        }

//        Integer carForMapperCount = carInfoService.getInuseCarCount(ids, date);
        Integer carCount = applyCarDataVo.getAllCarCount();
        Integer inuseCount = applyCarDataVo.getInuseCount();

        if (carCount > 0) {
            //空置数
            int vcantCount = carCount - inuseCount;
            applyCarDataVo.setCarVacantCount(vcantCount);
            //空置率
            DecimalFormat df = new DecimalFormat("0.000");
            String format = df.format((double) vcantCount / carCount * 100);
            Double dou = Double.valueOf(format);
            String s = roundStr(dou, 2);
            applyCarDataVo.setVacantRate(s + "%");
        } else {
            applyCarDataVo.setCarVacantCount(carCount);
        }
        return applyCarDataVo;
    }

    /**
     * 企业警情数据
     *
     * @param timeType
     * @return
     */
    @Override
    public R getAlarmData(Integer timeType, EtpInfo etpInfo) {
        OvmsUser user = SecurityUtils.getUser();
        Integer etpId = user.getEtpId();
        if (etpInfo.getId() != null) {
            etpId = etpInfo.getId();
        }

        //获取该企业下的后代企业ids
//        List<Integer> ids = carDeviceService.getDescendantForEtpId(etpId);
//        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(etpId);
//        EtpInfoSVo etpInfoSVo = currentAndParents1.get(0);
//        List<Integer> ids = etpInfoSVo.getIds();
//        ids.add(etpId);
        Date date = this.getDate(timeType);
        String s = DateUtil.formatDateTime(date);
        R alarmDataMultiEtp = alarmFeign.getAlarmDataMultiEtp(etpId, s);
        return alarmDataMultiEtp;
//        int accelerate = 0;
//        int decelerate = 0;
//        int turnAround = 0;
//        int speeding = 0;
//        int pullOut = 0;
//        int tow = 0;
//        int ignition = 0;
//        int waterTemp = 0;
//        int malfunction = 0;
//        int collision = 0;
//        int fence = 0;
//
//        List<Integer> collect = ids.stream().distinct().collect(Collectors.toList());
//        for (Integer id : collect) {
//            R alarmData = alarmFeign.getAlarmData(id, s);
//            Map data = (Map) alarmData.getData();
//            accelerate += (Integer) data.get("accelerate");
//            decelerate += (Integer) data.get("decelerate");
//            turnAround += (Integer) data.get("turnAround");
//            speeding += (Integer) data.get("speeding");
//            pullOut += (Integer) data.get("pullOut");
//            tow += (Integer) data.get("tow");
//            ignition += (Integer) data.get("ignition");
//            waterTemp += (Integer) data.get("waterTemp");
//            malfunction += (Integer) data.get("malfunction");
//            collision += (Integer) data.get("collision");
//            fence += (Integer) data.get("fence");
//        }
//        AlarmDataVo alarmDataVo = new AlarmDataVo();
//        alarmDataVo.setAccelerate(accelerate);
//        alarmDataVo.setDecelerate(decelerate);
//        alarmDataVo.setTurnAround(turnAround);
//        alarmDataVo.setSpeeding(speeding);
//        alarmDataVo.setPullOut(pullOut);
//        alarmDataVo.setTow(tow);
//        alarmDataVo.setIgnition(ignition);
//        alarmDataVo.setWaterTemp(waterTemp);
//        alarmDataVo.setMalfunction(malfunction);
//        alarmDataVo.setCollision(collision);
//        alarmDataVo.setFence(fence);
//        return R.ok(alarmDataVo);
    }

    private Date getDate(Integer timeType) {
        //当天的开始时间
        Date date = DateUtil.beginOfDay(DateUtil.date());
        if (timeType == TimeTypeConstant.SEVEN_DAY) {
            date = DateUtil.offsetDay(date, -7);
        }
        if (timeType == TimeTypeConstant.FIFTEEN_DAY) {
            date = DateUtil.offsetDay(date, -15);
        }
        if (timeType == TimeTypeConstant.THIRTY_DAY) {
            date = DateUtil.offsetDay(date, -30);
        }
        if (timeType == TimeTypeConstant.THREE_MONTHS) {
            date = DateUtil.offsetMonth(date, -3);
        }
        if (timeType == TimeTypeConstant.SIX_MONTHS) {
            date = DateUtil.offsetMonth(date, -6);
        }
        if (timeType == TimeTypeConstant.ONE_YEAR) {
            date = DateUtil.offset(date, DateField.YEAR, -1);
        }
        return date;
    }

}
